#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QStringList wordList;
    wordList << "entero" << "arreglo" << "cadena"
             << "real" << "booleano" << "caracter"
             << "registro"<< "funcion"<< "procedimiento"
             << "para" << "hasta" << "mientras"
             << "si" << "repita" << "caso"<< "llamar"
             << "escriba"<< "lea"<< "sino" << "entonces"
             << "haga"<< "inicio" << "fin"<< "pin"<< "entrada"
             << "salida"<< "bajo"<< "alto"<< "modo";
    QCompleter *completer = new QCompleter(wordList, this);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    this->ui->notelpp->setCompleter(completer);
    new Highlighter(this->ui->notelpp->document());





}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::save(){
    if (this->ActualDir.isEmpty()) {
        return saveAs();
    } else {
        return saveFile(this->ActualDir);
    }
}

bool MainWindow::saveAs(){
    QString fileName = QFileDialog::getSaveFileName(this,tr("Save File As"), "/", tr("LPP Files (*.lpp)"));
    if (fileName.isEmpty())
        return false;

    return saveFile(fileName);
}

bool MainWindow::saveFile(QString fileName){
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("Application"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return false;
    }

    QTextStream out(&file);
    out << this->ui->notelpp->toPlainText();
    setCurrentFile(fileName);
    this->ui->statusBar->showMessage(tr("File saved"), 2000);
    return true;
}

void MainWindow::setCurrentFile(QString filename){
    this->ActualDir = filename;
    this->ui->notelpp->document()->setModified(false);
}

bool MainWindow::maybeSave(){
    if (this->ui->notelpp->document()->isModified()) {
        QMessageBox::StandardButton ret;
        ret = QMessageBox::warning(this, tr("Application"),
                     tr("The document has been modified.\n"
                        "Do you want to save your changes?"),
                     QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        if (ret == QMessageBox::Save)
            return save();
        else if (ret == QMessageBox::Cancel)
            return false;
    }
    return true;
}

void MainWindow::loadFile(QString FileName){
    QFile file(FileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("Application"),
                             tr("Cannot read file %1:\n%2.")
                             .arg(FileName)
                             .arg(file.errorString()));
        return;
    }
    QTextStream in(&file);

    this->ui->notelpp->setPlainText(in.readAll());
    this->ui->consola->clear();
    setCurrentFile(FileName);
    this->ui->statusBar->showMessage(tr("File loaded"), 2000);
}

void MainWindow::open(){
    if (maybeSave()) {
        QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), "/", tr("LPP Files (*.lpp)"));
        if (!fileName.isEmpty())
            loadFile(fileName);
    }
}

void MainWindow::newFile(){
    if (maybeSave()) {
        this->ui->notelpp->clear();
        this->ui->consola->clear();
        setCurrentFile("");
    }
}

void MainWindow::on_actionOpen_triggered()
{
    open();
}

void MainWindow::on_actionCompile_triggered()
{   maybeSave();
    this->ui->consola->clear();
    this->ui->noteC->clear();
    ui->consola->append("Compaling.... "+this->ActualDir);
    try{
        Sintactico *sintatico = new Sintactico(this->ActualDir.toStdString());
        Sentencia* sentencia = sintatico->S();
        if(sentencia!=0){
            sentencia->validarSemantica(sintatico->getTablaTipos(),sintatico->getTablaVaribales());

        }
        GenerarCodigo *gc = new GenerarCodigo(sentencia,sintatico->getTablaVaribales(),sintatico->getTablaTipos());
        string codigo = gc->getCodigo();
        QString Qcodigo = QString::fromStdString(codigo);

        this->ui->noteC->append(Qcodigo);
        //Print *print = new Print(sentencia);
        QString newfile = this->ActualDir;
        int pount = newfile.indexOf(".");
        newfile.truncate(pount);
        newfile.append(".c");
        QFile file(newfile);
        if (!file.open(QFile::WriteOnly | QFile::Text)) {
            QMessageBox::warning(this, tr("Application"),
                                 tr("Cannot write file %1:\n%2.")
                                 .arg(newfile)
                                 .arg(file.errorString()));

        }

        QTextStream out(&file);
        out << this->ui->noteC->toPlainText();

        ui->consola->append("Compaling Finish");
    }catch(exception e){
        QString sms = e.what();
        int find = sms.indexOf("Fila:");
        QString s;
        find = sms.length()-find;
        find=find-5;
        s.setNum(find,10);
        QString filasms = sms.right(find);
        bool ok;
        find = filasms.toInt(&ok,10);
        ui->consola->append(sms);
        QTextCursor cursor = this->ui->notelpp->textCursor();
        cursor.movePosition(QTextCursor::Start);
        cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor,find);
        cursor.select(QTextCursor::LineUnderCursor);
        this->ui->notelpp->setTextCursor(cursor);


    }
}

void MainWindow::on_actionSave_2_triggered()
{
    save();
}

void MainWindow::on_actionSave_As_triggered()
{
    saveAs();
}

void MainWindow::on_actionNew_triggered()
{
    newFile();
}

void MainWindow::on_actionSi_Fin_Si_triggered()
{
    this->ui->notelpp->insertPlainText("SI /*Exprecion*/ ENTONCES\n");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("FIN SI\n ");
}

void MainWindow::on_actionSi_Sino_Fin_Si_triggered()
{
    this->ui->notelpp->insertPlainText("SI /*Exprecion*/ ENTONCES\n");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("SINO\n ");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("FIN SI\n ");

}

void MainWindow::on_actionCaso_Fin_Caso_triggered()
{
    this->ui->notelpp->insertPlainText("Caso /*Variable*/\n");
    this->ui->notelpp->insertPlainText("/*Bloques del Caso*/\n ");
    this->ui->notelpp->insertPlainText("Fin Caso\n ");

}

void MainWindow::on_actionPara_Fin_Para_triggered()
{
    this->ui->notelpp->insertPlainText("Para /*Variable*/ <- /*Valor Inicial*/ Hasta /*Valor Final*/ Haga\n ");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("Fin Para\n ");
}

void MainWindow::on_actionMientras_Fin_Mientras_triggered()
{
    this->ui->notelpp->insertPlainText("Mientras /*Condicion*/ Haga\n");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("Fin Mientras\n ");

}

void MainWindow::on_actionRepita_Hasta_triggered()
{
    this->ui->notelpp->insertPlainText("Repita\n");
    this->ui->notelpp->insertPlainText("/*Instrucciones*/\n ");
    this->ui->notelpp->insertPlainText("Hasta /*Condicion*/\n ");
}




